﻿Imports System.Net.Sockets
Imports System.Threading
Imports System.Net
Imports System.ComponentModel

Public Class TcpServerManager
    Inherits System.ComponentModel.Component

#Region "variable"
    Private Const BUFFER_SIZE As Long = 8L * 1024L '8K
    Private m_TcpListner As TcpListener = Nothing
#End Region

#Region "property"

    Private m_SerIP As String = "127.0.0.1"
    <DefaultValue(GetType(System.String), "127.0.0.1")> _
    Public Property SerIP() As String
        Get
            Return m_SerIP
        End Get
        Set(ByVal value As String)
            m_SerIP = value
        End Set
    End Property

    Private m_SerPort As Integer = 9999
    <DefaultValue(GetType(System.Int32), "9999")> _
    Public Property SerPort() As Integer
        Get
            Return m_SerPort
        End Get
        Set(ByVal value As Integer)
            m_SerPort = value
        End Set
    End Property

    Private m_MaxClientCount As Integer = 10
    <DefaultValue(GetType(System.Int32), "10")> _
    Public Property MaxClientCount() As Integer
        Get
            Return m_MaxClientCount
        End Get
        Set(ByVal value As Integer)
            m_MaxClientCount = value
        End Set
    End Property

    Private m_BufferSize As Long = BUFFER_SIZE
    <DefaultValue(GetType(Long), "8192")> _
    Public Property BufferSize() As Long
        Get
            Return m_BufferSize
        End Get
        Set(ByVal value As Long)
            m_BufferSize = value
        End Set
    End Property

    Private m_Active As Boolean = False
    Public Property Active() As Boolean
        Get
            Return m_Active
        End Get
        Set(ByVal value As Boolean)
            m_Active = value
        End Set
    End Property


    Private m_DicClient As Dictionary(Of String, Sockets.Socket)
    Public ReadOnly Property DicClient() As Dictionary(Of String, Sockets.Socket)
        Get
            Return m_DicClient
        End Get
    End Property

    ''' <summary>
    ''' 连接中的客户端数量
    ''' </summary>
    Public ReadOnly Property ClientCount() As Integer
        Get
            Return Me.m_DicClient.Count
        End Get
    End Property


#End Region

#Region "constructed function"

    Public Sub New()
        Me.m_DicClient = New Dictionary(Of String, Sockets.Socket)
        Me.m_TcpListner = New TcpListener(IPAddress.Any, SerPort)
    End Sub

    Public Sub New(ByVal serPort As Integer)
        Me.New(serPort, 10)
    End Sub

    Public Sub New(ByVal serPort As Integer, ByVal maxClintCount As Integer)
        Me.m_SerPort = serPort
        Me.m_MaxClientCount = maxClintCount

        Me.m_DicClient = New Dictionary(Of String, Sockets.Socket)
        Me.m_TcpListner = New TcpListener(IPAddress.Any, serPort)
    End Sub

    Public Sub New(ByVal serIP As String, ByVal serPort As Integer)
        Me.New(serIP, serPort, 10)
    End Sub

    Public Sub New(ByVal serIP As String, ByVal serPort As Integer, ByVal maxClintCount As Integer)
        Me.m_SerIP = serIP
        Me.m_SerPort = serPort
        Me.m_MaxClientCount = maxClintCount

        Me.m_DicClient = New Dictionary(Of String, Sockets.Socket)
        Me.m_TcpListner = New TcpListener(IPAddress.Parse(serIP), serPort)
    End Sub

#End Region

#Region "delegate"

#End Region

#Region "events"
    ''' <summary>
    ''' 建立连接事件
    ''' </summary>
    ''' <remarks></remarks>
    Public Event Connect As ConnectEventHandler
    Public Overridable Sub OnConnect(ByVal e As ConnectEventArgs)
        If e IsNot Nothing Then
            RaiseEvent Connect(Me, e)
        End If
    End Sub

    ''' <summary>
    ''' 注销连接事件
    ''' </summary>
    ''' <remarks></remarks>
    Public Event DisConnect As DisConnectEventHandler
    Public Overridable Sub OnDisConnect(ByVal e As DisConnectEventArgs)
        If e IsNot Nothing Then
            RaiseEvent DisConnect(Me, e)
        End If
    End Sub

    ''' <summary>
    ''' 数据到达事件
    ''' </summary>
    ''' <remarks></remarks>
    Public Event DataArrivaled As DataArrivaledEventHandler
    Public Overridable Sub OnDataArrivaled(ByVal e As DataArrivaledEventArgs)
        If e IsNot Nothing Then
            RaiseEvent DataArrivaled(Me, e)
        End If
    End Sub
#End Region

#Region "private method"

    ''' <summary>
    ''' 开始接受客户端Socket
    ''' </summary>
    Private Sub beginAcceptSocket()
        ' Accept the connection. 
        ' BeginAcceptSocket() creates the accepted socket.
        Me.m_TcpListner.BeginAcceptSocket(New AsyncCallback(AddressOf Me.doAcceptSocket), Me.m_TcpListner)
    End Sub

    ''' <summary>
    ''' 接受Socket的委托方法
    ''' </summary>
    ''' <param name="ar"></param>
    ''' <remarks></remarks>
    Private Sub doAcceptSocket(ByVal ar As IAsyncResult)
        Dim _TcpListener As TcpListener = DirectCast(ar.AsyncState, TcpListener)

        Try
            Dim _Socket As Sockets.Socket = Nothing
            Try
                _Socket = _TcpListener.EndAcceptSocket(ar)
            Catch ex As ObjectDisposedException
                Exit Sub
            End Try

            Me.OnConnect(New ConnectEventArgs(_Socket, Nothing, False, Nothing))

            '[Begin]创建独立的ServerSocket----------------------------------------------------------
            Dim _TcpServer As New TcpServer(_Socket, Me.m_BufferSize)
            With _TcpServer
                AddHandler .DataArrivaled, AddressOf Me.TcpServer_DataArrivaled
                AddHandler .DisConnect, AddressOf Me.TcpServer_DisConnect
                ThreadPool.QueueUserWorkItem(AddressOf .Start, _Socket)
            End With
            '[End]创建独立的ServerSocket------------------------------------------------------------

            If Me.Active = True AndAlso Me.ClientCount < (Me.m_MaxClientCount - 1) Then
                Me.beginAcceptSocket()
            Else
                Me.m_TcpListner.Stop()
            End If
        Catch ex As Exception
            Me.OnConnect(New ConnectEventArgs(ex, False, Nothing))
        End Try
    End Sub

    Private Sub TcpServer_DataArrivaled(ByVal sender As Object, ByVal e As DataArrivaledEventArgs)
        Me.OnDataArrivaled(e)
    End Sub

    Private Sub TcpServer_DisConnect(ByVal sender As Object, ByVal e As DisConnectEventArgs)
        Me.OnDisConnect(e)
    End Sub

#End Region

#Region "public method"

    ''' <summary>
    ''' 开始监听端口
    ''' </summary>
    Public Sub [Start]()
        Me.m_Active = True

        Me.m_TcpListner.Start(Me.m_MaxClientCount)
        Me.beginAcceptSocket()
    End Sub

    ''' <summary>
    ''' 停止监听
    ''' </summary>
    Public Sub [Stop]()
        Me.m_Active = False

        For Each kvp As KeyValuePair(Of String, Sockets.Socket) In Me.m_DicClient
            kvp.Value.Disconnect(True)
        Next

        Me.m_TcpListner.Stop()
    End Sub

    ''' <summary>
    ''' 添加客户端到列表中
    ''' </summary>
    ''' <param name="key">GUID字符串</param>
    ''' <param name="socketClient">接受到的客户端Socket对象</param>
    Public Sub AddClient(ByVal key As String, ByVal socketClient As Sockets.Socket)
        Me.m_DicClient.Add(key, socketClient)
    End Sub

    ''' <summary>
    ''' 移除客户端
    ''' </summary>
    ''' <param name="key">GUID字符串</param>
    Public Sub RemoveClient(ByVal key As String)
        Me.m_DicClient.Remove(key)
    End Sub

    ''' <summary>
    ''' 移除所有客户端
    ''' </summary>
    Public Sub RemoveAllClient()
        Me.m_DicClient.Clear()
    End Sub


    ''' <summary>
    ''' 发送数据
    ''' </summary>
    ''' <param name="key"></param>
    ''' <param name="data"></param>
    ''' <remarks></remarks>
    Public Sub Send(ByVal key As String, ByVal data() As Byte)
        Dim _ClientSocket As Sockets.Socket = Me.m_DicClient(key)
        _ClientSocket.Send(data)
    End Sub

#End Region


End Class
